package top.huxy.mybatis.config;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import top.huxy.mybatis.core.DynamicDataSource;
import top.huxy.mybatis.core.HuxyDataSourceProperties;
import top.huxy.mybatis.core.SingleDataProperties;

import javax.sql.DataSource;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * @author aproz
 * @Date 2022/5/25
 */
@Configuration
@EnableConfigurationProperties(HuxyDataSourceProperties.class)
@ComponentScan("top.huxy.mybatis.config")
@Slf4j
public class HuxyDataSourceAutoConfig {
    public static final String DEFAULT_DATA_SOURCE_NAME = "DEFAULT";

    @Autowired
    HuxyDataSourceProperties properties;

    @Bean
    @Primary
    public DynamicDataSource dataSource() {
        String defaultDataSource = properties.getDefaultDataSource();
        if (defaultDataSource == null || defaultDataSource.trim().length() == 0) {
            return singleDataSource();
        } else {
            return multipleDataSource(defaultDataSource);
        }
    }

    private DynamicDataSource multipleDataSource(String defaultDataSource) {
        Map<String, Object> datasource = properties.getDatasource();
        if(datasource==null){
            throw new NullPointerException("没有配置数据源");
        }
        if (datasource.isEmpty()) {
            log.warn("没有多数据源的配置");
        }

        Map<String, SingleDataProperties> datasources = new HashMap<>();

        //准备配置
        for (Map.Entry<String, Object> idAndProperties : datasource.entrySet()) {
            String key = idAndProperties.getKey();
            Object value = idAndProperties.getValue();
            Object o = JSON.toJSON(value);
            if (o instanceof JSONObject) {
                SingleDataProperties properties = ((JSONObject) o).to(SingleDataProperties.class);
                datasources.put(key, properties);
            }
        }

        //将配置实例化成dataSourceMap
        Map<Object, Object> dataSourceMap = new HashMap<>(datasources.size());
        for (Map.Entry<String, SingleDataProperties> kv : datasources.entrySet()) {
            dataSourceMap.put(kv.getKey(), createDataSource(kv.getValue()));
        }
        Object o = dataSourceMap.get(defaultDataSource);
        if (o == null) {
            log.warn("无法找到默认数据源" + defaultDataSource);
            if (dataSourceMap.size() == 1) {
                Map.Entry<Object, Object> first = dataSourceMap.entrySet().stream().findFirst().get();
                o = first.getValue();
                log.warn("已自动使用唯一数据源" + first.getKey() + "作为默认数据源");
            }
        }

        return new DynamicDataSource(((DataSource) o), dataSourceMap);
    }

    private DynamicDataSource singleDataSource() {
        Map<String, Object> datasource = properties.getDatasource();
        if(datasource==null){
            throw new NullPointerException("没有配置数据源");
        }
        SingleDataProperties properties = new JSONObject(datasource).to(SingleDataProperties.class);
        DataSource dataSource = createDataSource(properties);
        return new DynamicDataSource(dataSource, Collections.singletonMap("DEFAULT", dataSource));
    }

    private DataSource createDataSource(SingleDataProperties properties) {
        return DataSourceBuilder
                .create()
                .type(properties.getType())
                .url(properties.getUrl())
                .username(properties.getUsername())
                .driverClassName(properties.getDriverClassName())
                .password(properties.getPassword())
                .build();
    }
}
